-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix passing of linker with target-applies-to-host and an implicit target #14206
base: master
Are you sure you want to change the base?
Conversation
@@ -25,7 +25,8 @@ use std::path::{Path, PathBuf}; | |||
use std::str::{self, FromStr}; | |||
use std::sync::Arc; | |||
|
|||
/// Information about the platform target gleaned from querying rustc. | |||
/// Information about the platform target gleaned from querying rustc and from | |||
/// merging configs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment didn't really fit with this struct containing rustflags
(which predates me working on target-applies-to-host). Putting linker
in it makes the mismatch slightly worse, so I thought I'd update the comment.
I'm not entirely thrilled with the phrasing. If someone has a suggestion for better phrasing I'd be happy to take it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe somthing like?
/// Information and compiler flags for the platform target gleaned from querying rustc
/// and from Cargo configurations.
Going to propose this change to the Cargo team on Zulip t-cargo soon. Probably tomorrow. I don't think we need to go through an FCP process for updating an unstable feature. Still no harm to get a soft consensus from the team. |
Sounds good, I'll keep a tab open to that in case there's anything I can contribute. |
@@ -21,7 +21,8 @@ fn bad1() { | |||
p.cargo("check -v --target=nonexistent-target") | |||
.with_status(101) | |||
.with_stderr_data(str![[r#" | |||
[ERROR] expected table for configuration key `target.nonexistent-target`, but found string in [ROOT]/foo/.cargo/config.toml | |||
[ERROR] invalid configuration for key `target.nonexistent-target` | |||
expected a table, but found a string for `target.nonexistent-target` in [ROOT]/foo/.cargo/config.toml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did this test change?
Because we parse this configuration in two places, in two slightly different ways, and we return slightly different error messages depending on what parsing path we went down. Moving target_linker
so that it's called much earlier in the process switched which code path tries to parse this first, and thus which error we get.
I don't think the errors are meaningfully different, so I'm proposing just adopting the error that happens to be returned first as correct. If anyone disagrees, I think the best alternative would be to simply make the two error paths return the same string. That's slightly awkward because the error path we are now hitting is generic over types so we'd have to either special case "table" (which wouldn't be hard) or decide we're happy with the same syntax for all types.
If there's any interest, the function call paths to these errors was:
RustcTargetData::new -> TargetInfo::merge_compile_kind -> gctx.target_cfg_triple -> target::load_target_triple -> target::load_config_table -> gctx.get::<OptValue<PathAndArgs>>("{prefix}.runner") -> T::deserialize -> Deserializer::deserialize_option -> gctx.has_key -> self.get_cv -> self.get_cv_helper -> bail!
And is now
RustcTargetData::new -> TargetInfo::new -> target_linker -> gctx.target_cfgs -> target::load_target_cfgs -> gctx.get::<BTreeMap<String, TargetCfgConfig>>("target") -> T::deserialize -> ConfigMapAccess::new_map -> gctx.get_table -> gctx.expected
☔ The latest upstream changes (presumably #14243) made this pull request unmergeable. Please resolve the merge conflicts. |
Huh, why isn't CI running? Rebased on master (at least as of a few hours ago) and changed from using |
…alse and no target flags
…by storing it in `Unit`
That's a better guess than mine that github was unhappy about the fact that there was a few hours between me making the changes and pushing them. Rebased on master again (no longer 4 hours in the past). |
@@ -25,7 +25,8 @@ use std::path::{Path, PathBuf}; | |||
use std::str::{self, FromStr}; | |||
use std::sync::Arc; | |||
|
|||
/// Information about the platform target gleaned from querying rustc. | |||
/// Information about the platform target gleaned from querying rustc and from | |||
/// merging configs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe somthing like?
/// Information and compiler flags for the platform target gleaned from querying rustc
/// and from Cargo configurations.
if requested_kinds != [CompileKind::Host] { | ||
// When an explicit target flag is passed rustflags are ignored for host artifacts. | ||
config.rustflags = None; | ||
config.rustdocflags = None; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😮💨 seems like a bad code smell to me, but I understand it is for maintaining the dual bad behavior that linker is respected but rustflags is not, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly.
And I 100% agree with bad code smell, but this feels less bad to me than the pre-existing reality that host_config is just storing incorrect rustflags in this case. It's one of the things that took me awhile to understand the first time I started working on this code (and why I added that comment on line 943 that I now get to delete).
A more ambitious refactoring option might be to try and push all this logic into something like gctx.host_cfg_triple
. I remember trying that when I wrote this and rejecting it, but I don't remember why I rejected it and I'd be happy to give it another shot if you think that it might be cleaner.
@@ -826,6 +836,42 @@ fn rustflags_from_target( | |||
} | |||
} | |||
|
|||
/// Gets the user-specified linker for a particular host or target from the configuration. | |||
fn target_linker( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After this PR the target_linker
is called when gleaning target info. Before this, it was called during Compilation::new
in compile_ws
. This may fail some commands like cargo metadata
, cargo tree
or cargo -Zunstable-options rustc --print
due to bad configuration files.
For example, cargo metadata
failed with this configs but not before.
[target.'cfg(target_arch = "x86_64")']
linker = "foo"
[target.'cfg(target_os = "linux")']
linker = "foo"
This might not be ideal because those commands don't need target infos.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I entirely missed that this was a problem.
I don't see a good solution to this, I'll come back with a fresh set of eyes tomorrow and see if that changes.
Right now my take is it's either this (bad), don't fix this issue at all (also bad), or doing something involving not so clean code to defer actually returning the error (also bad). But I think there's a small chance I can find a better way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, the current approach is not too bad for normal users.
However, I know some enterprise users have weird multi-level configuration setup. And may move projects among different directories. This is also bad because you cannot opt out directory-probing for configuration files (which Cargo may provide an escape patch?).
☔ The latest upstream changes (presumably #14273) made this pull request unmergeable. Please resolve the merge conflicts. |
☔ The latest upstream changes (possibly 081d7ba) made this pull request unmergeable. Please resolve the merge conflicts. |
What does this PR try to resolve?
Fixes the linker half of #14195.
The second commit ("Fix
linker
value withtargeta-applies-to-host
and implicit target by storing it inUnit
") does just that following the same structure as #13900, though the current place wherelinker
is stored is a bit farther away in the code base the logical change and justification for it is the same as in #13900. As part of this we end up passingtarget_config
intoTargetInfo::new
to get convenient access to thelinker
argument, there is an alternative here that I felt was worse to simply fetch thelinker
field from gctx, which is more like howrustflags
currently works. This ends up leaving a bit of a footgun though, where thattarget_config
doesn't necessarily have the right rustflags values despite being passed in.The third commit ("Read
rustflags
fromTargetConfig
inTargetInfo::new
") changesrustflags
to be read fromTargetConfig
likelinker
works above. Apart from being arguably cleaner code, this removes the footgun I introduced in the second commit, and removes an existing footgun where the rustflags inRustcTargetData::host_config
aren't necessarily correct (though it continues to be the case thatTargetConfig
s don't necessarily have the right values if there is another source of values). It was also simply made easier to do now since the second commit already conceded to making the change thatTargetInfo::new
requires aTargetConfig
. That said, it is largely independent from this PR and could be removed if it is a sticking point.The first commit just adds a test.
How should we test and review this PR?
For testing, the second commit comes with it's own test (from the first commit), the third commit relies on existing tests to catch any mistakes.
Additional information
The other half of fixing this issue is #14205, the two PRs will have a merge conflict as a result of field ordering in
Unit
but are otherwise independent.@rustbot label: Z-target-applies-to-host
r? @weihanglo if you're willing to look at this